home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
ada
/
gnat1792.zip
/
gnat179b
/
t-adainc
/
s-tatise.adb
< prev
next >
Wrap
Text File
|
1994-05-19
|
21KB
|
648 lines
------------------------------------------------------------------------------
-- --
-- GNU ADA RUNTIME LIBRARY (GNARL) COMPONENTS --
-- --
-- S Y S T E M . T A S K _ T I M E R _ S E R V I C E --
-- --
-- B o d y --
-- --
-- $Revision: 1.7 $ --
-- --
-- Copyright (c) 1991,1992,1993, FSU, All Rights Reserved --
-- --
-- GNARL is free software; you can redistribute it and/or modify it under --
-- terms of the GNU Library General Public License as published by the --
-- Free Software Foundation; either version 2, or (at your option) any --
-- later version. GNARL is distributed in the hope that it will be use- --
-- ful, but but WITHOUT ANY WARRANTY; without even the implied warranty of --
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Gen- --
-- eral Library Public License for more details. You should have received --
-- a copy of the GNU Library General Public License along with GNARL; see --
-- file COPYING. If not, write to the Free Software Foundation, 675 Mass --
-- Ave, Cambridge, MA 02139, USA. --
-- --
------------------------------------------------------------------------------
with Ada.Calendar.Conv;
with System.Compiler_Exceptions;
with System.Real_Time.Conv;
with System.Task_Primitives;
with System.Tasking.Stages;
with System.Task_Clock.Machine_Specifics;
with Unchecked_Conversion;
package body System.Task_Timer_Service is
use System.Tasking.Protected_Objects;
use System.Tasking;
use System.Task_Clock;
-- Included use clause for comparison operators
function Clock return Stimespec
renames Task_Clock.Machine_Specifics.Clock;
type Q_Rec;
type Q_Link is access Q_Rec;
type Q_Rec is record
S_O : Signal_Object.O_Type;
T : Task_Clock.Stimespec; -- wake up time
Next : Q_Link;
Previous : Q_Link;
end record;
Q_Head : Q_Link := null;
Timer_Condition : Task_Primitives.Condition_Variable;
Timer_Lock : Task_Primitives.Lock;
-- Hand Traslated code will be provided here. ???
function To_Access is new
Unchecked_Conversion (System.Address, Protection_Access);
-------------------
-- Signal_Object --
-------------------
package body Signal_Object is
--------------------------------------
-- Signal_Object.Signal_Unprotected --
--------------------------------------
procedure Signal_Unprotected (Open : in out boolean) is
begin
Open := true;
end Signal_Unprotected;
procedure Signal (PO : in out O_Type) is
PS : Boolean;
begin
Tasking.Protected_Objects.Lock (To_Access (PO.Object'Address));
begin
Signal_Unprotected (PO.Open);
exception
when others =>
Service_Entries (PO, PS);
Tasking.Protected_Objects.Unlock (
To_Access (PO.Object'Address));
raise;
end;
Service_Entries (PO, PS);
-- Barriers may have changed
Tasking.Protected_Objects.Unlock (To_Access (PO.Object'Address));
end Signal;
------------------------------------------
-- Signal_Object.Wait_Count_Unprotected --
------------------------------------------
function Wait_Count_Unprotected (Object : Protection) return integer is
begin
-- Find the number of calls waiting on the specified entry
return Protected_Count (Object, 1);
end Wait_Count_Unprotected;
------------------------------
-- Signal_Object.Wait_Count --
------------------------------
procedure Wait_Count (PO : in out O_Type; W : out integer) is
begin
Tasking.Protected_Objects.Lock_Read_Only
(To_Access (PO.Object'Address));
W := Wait_Count_Unprotected (PO.Object);
Tasking.Protected_Objects.Unlock (To_Access (PO.Object'Address));
exception
when others =>
Tasking.Protected_Objects.Unlock (To_Access (PO.Object'Address));
raise;
end Wait_Count;
-----------------------------------
-- Signal_Object.Service_Entries --
-----------------------------------
procedure Service_Entries
(PO : in out O_Type;
Pending_Serviced : out Boolean)
is
subtype PO_Entry_Index is Protected_Entry_Index
range Null_Protected_Entry .. 1;
P : System.Address;
Barriers : Tasking.Barrier_Vector (1 .. 1);
E : PO_Entry_Index;
PS : Boolean;
Cumulative_PS : Boolean := False;
begin
loop
begin
Barriers (1) := PO.Open;
exception
when others =>
begin
Tasking.Protected_Objects.Broadcast_Program_Error
(To_Access (PO.Object'Address));
exception
when Program_Error =>
Tasking.Protected_Objects.Unlock
(To_Access (PO.Object'Address));
raise;
end;
end;
Tasking.Protected_Objects.Next_Entry_Call
(To_Access (PO.Object'Address), Barriers, P, E);
begin
case E is
when Null_Protected_Entry =>
-- No pending call to serve
exit;
when 1 =>
-- Code from the entry Wait
PO.Open := False;
Tasking.Protected_Objects.Complete_Entry_Body
(To_Access (PO.Object'Address), PS);
end case;
exception
when others =>
Tasking.Protected_Objects.Exceptional_Complete_Entry_Body (
Object => To_Access (PO.Object'Address),
Ex => Compiler_Exceptions.Current_Exception,
Pending_Serviced => PS);
end;
Cumulative_PS := Cumulative_PS or PS;
end loop;
Pending_Serviced := Cumulative_PS;
end Service_Entries;
end Signal_Object;
-----------
-- Timer --
-----------
package body Timer is
-------------------------------
-- Timer.Service_Unprotected --
-------------------------------
procedure Service_Unprotected (T : out Task_Clock.Stimespec) is
Q_Ptr : Q_Link := Q_Head;
W : integer;
begin
while Q_Ptr /= null loop
Signal_Object.Wait_Count (Q_Ptr.S_O, W);
if Q_Ptr.T < Clock or else W = 0 then
-- Wake up the waiting task
Signal_Object.Signal (Q_Ptr.S_O);
-- When it is done, all the pending calls are serviced
-- Therefore it is safe to finalize it.
Finalize_Protection (To_Access (Q_Ptr.S_O.Object'Address));
-- Remove the entry, case of head entry
if Q_Ptr = Q_Head then
Q_Head := Q_Ptr.Next;
if Q_Head /= null then
Q_Head.Previous := null;
end if;
-- Case of tail entry
elsif Q_Ptr.Next = null then
Q_Ptr.Previous.Next := null;
-- Case of middle entry